package com.github.gin.springboot.security;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.concurrent.atomic.AtomicInteger;

public class RetryLimitSimpleCredentialsMatcher extends HashedCredentialsMatcher {
	
	/*@Autowired
    private UserService userService;*/

    private Cache<String, AtomicInteger> passwordRetryCache;

    private Cache<Object, AuthenticationInfo> authenticationInfocache;
    
    private static final ThreadLocal<AtomicInteger> PASSWORD_RETRY_COUNT = new ThreadLocal<AtomicInteger>();

    public RetryLimitSimpleCredentialsMatcher(CacheManager cacheManager) {
        passwordRetryCache = cacheManager.getCache("passwordRetryCache");
        authenticationInfocache = cacheManager.getCache("authenticationCache");
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
    	LoginNamePasswordToken myToken = (LoginNamePasswordToken)token;
        //retry count + 1
        AtomicInteger retryCount = passwordRetryCache.get(myToken.getLoginName());
        if(retryCount == null) {
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(myToken.getLoginName(), retryCount);
        }
        if(retryCount.incrementAndGet() >= FormAuthenticationFilter.DEFAULT_PASSWORD_RETRY_COUNT) {
            //if retry count > 5 throw
            throw new ExcessiveAttemptsException();
        }

        boolean matches = super.doCredentialsMatch(token, info);
        if(matches) {

            /*if(StringUtils.isNotBlank(myToken.getLoginName())){
                User user = userService.getByLoginName(myToken.getLoginName());
                Subject subject = SecurityUtils.getSubject();
                Session session = subject.getSession();
                session.setAttribute("user", user);
            }*/

            //clear retry count
            passwordRetryCache.remove(myToken.getLoginName());
        }
        
        set(passwordRetryCache.get(myToken.getLoginName()));
        
        return matches;
    }
    
    public static AtomicInteger get(){
    	return PASSWORD_RETRY_COUNT.get();
    }
    
    public static void set(AtomicInteger retryCount){
    	PASSWORD_RETRY_COUNT.set(retryCount);
    }
}
